home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
util
/
gnu
/
xpdf-0.8-src.lha
/
xpdf-0.8-src
/
ltk
/
LTKTextIn.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1998-11-28
|
12KB
|
488 lines
//========================================================================
//
// LTKTextIn.cc
//
// Copyright 1996 Derek B. Noonburg
//
//========================================================================
#ifdef __GNUC__
#pragma implementation
#endif
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include "gtypes.h"
#include "GString.h"
#include "LTKWindow.h"
#include "LTKTextIn.h"
#include "LTKBorder.h"
#define horizBorder 2
#define vertBorder 2
LTKTextIn::LTKTextIn(char *name1, int widgetNum1, int minWidth1,
char *fontName1, LTKStringValCbk doneCbk1,
char *tabTarget1):
LTKWidget(name1, widgetNum1) {
minWidth = minWidth1;
text = new GString();
active = gFalse;
firstChar = 0;
cursor = 0;
selectionEnd = 0;
dragging = gFalse;
doneCbk = doneCbk1;
tabTarget = tabTarget1;
fontName = fontName1;
fontStruct = NULL;
textGC = None;
}
LTKTextIn::~LTKTextIn() {
delete text;
if (fontName && fontStruct) {
XFreeFont(getDisplay(), fontStruct);
XFreeGC(getDisplay(), textGC);
}
}
long LTKTextIn::getEventMask() {
return LTKWidget::getEventMask() |
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionHintMask | KeyPressMask;
}
void LTKTextIn::setText(char *s) {
delete text;
text = new GString(s);
firstChar = 0;
if (getXWindow() != None && active)
xorCursor();
cursor = selectionEnd = 0;
if (getXWindow() != None) {
redrawTail(0);
if (active)
xorCursor();
}
}
void LTKTextIn::layout1() {
XGCValues gcValues;
if (textGC == None) {
if (fontName &&
(fontStruct = XLoadQueryFont(getDisplay(), fontName))) {
XGetGCValues(getDisplay(), getFgGC(),
GCForeground | GCBackground | GCGraphicsExposures,
&gcValues);
gcValues.font = fontStruct->fid;
textGC = XCreateGC(getDisplay(), parent->getXWindow(),
GCForeground | GCBackground | GCGraphicsExposures |
GCFont, &gcValues);
} else {
fontName = NULL;
fontStruct = parent->getXFontStruct();
textGC = getFgGC();
}
}
textHeight = fontStruct->ascent + fontStruct->descent;
textBase = fontStruct->ascent;
width = minWidth * fontStruct->max_bounds.width + 2 * horizBorder + 1;
height = textHeight + 2 * vertBorder;
}
void LTKTextIn::layout3() {
XRectangle rect;
LTKWidget::layout3();
rect.x = horizBorder - 1; // need one pixel in left border for cursor
rect.y = 0;
rect.width = width - 2 * horizBorder + 1;
rect.height = height;
XSetClipRectangles(getDisplay(), textGC, 0, 0, &rect, 1, Unsorted);
}
void LTKTextIn::redraw() {
XFillRectangle(getDisplay(), xwin, getBgGC(), 0, 0, width, height);
redrawTail(firstChar);
if (active)
xorCursor();
}
void LTKTextIn::buttonPress(int mx, int my, int button, GBool dblClick) {
// move cursor
if (button == 1) {
xorCursor();
cursor = xToCursor(mx);
if (cursor < firstChar)
cursor = firstChar;
selectionEnd = cursor;
xorCursor();
dragging = gTrue;
dragAnchor = cursor;
// paste
} else if (button == 2) {
parent->requestPaste(this);
}
}
void LTKTextIn::buttonRelease(int mx, int my, int button, GBool click) {
dragging = gFalse;
if (cursor != selectionEnd)
parent->setSelection(this, new GString(text->getCString() + cursor,
selectionEnd - cursor));
}
void LTKTextIn::mouseMove(int mx, int my, int btn) {
int newCursor, newSelectionEnd;
int i;
if (dragging) {
i = xToCursor(mx);
if (i >= dragAnchor) {
newCursor = dragAnchor;
newSelectionEnd = i;
} else {
newCursor = i;
newSelectionEnd = dragAnchor;
}
if (newCursor != cursor || newSelectionEnd != selectionEnd)
moveCursor(newCursor, newSelectionEnd, i);
}
}
void LTKTextIn::activate(GBool on) {
if (active != on) {
if (on) {
xorCursor();
parent->setKeyWidget(this);
active = gTrue;
} else {
xorCursor();
selectionEnd = cursor;
parent->setKeyWidget(NULL);
active = gFalse;
if (doneCbk)
(*doneCbk)(this, widgetNum, text);
}
}
}
void LTKTextIn::keyPress(KeySym key, Guint modifiers, char *s, int n) {
int newCursor, newSelectionEnd;
int redrawPos;
GBool killSelection;
LTKWidget *widget;
newCursor = cursor;
killSelection = gTrue;
redrawPos = -1;
if (key == XK_Left) { // left arrow
if (cursor > 0)
--newCursor;
} else if (key == XK_Right) { // right arrow
if (cursor < text->getLength())
++newCursor;
} else if (n >= 1) {
switch (s[0]) {
case '\001': // ^A
newCursor = 0;
break;
case '\002': // ^B
if (cursor > 0)
--newCursor;
break;
case '\005': // ^E
newCursor = text->getLength();
break;
case '\006': // ^F
if (cursor < text->getLength())
++newCursor;
break;
case '\014': // ^L
redrawPos = firstChar;
killSelection = gFalse;
break;
case '\b': // bs
case '\177': // del
if (selectionEnd > cursor) {
text->del(cursor, selectionEnd - cursor);
redrawPos = cursor;
} else if (cursor > 0) {
text->del(cursor - 1);
--newCursor;
redrawPos = newCursor;
}
break;
case '\004': // ^D
if (selectionEnd > cursor) {
text->del(cursor, selectionEnd - cursor);
redrawPos = cursor;
} else if (cursor < text->getLength()) {
text->del(cursor);
redrawPos = cursor;
}
break;
case '\013': // ^K
text->del(cursor, text->getLength() - cursor);
redrawPos = cursor;
break;
case '\025': // ^U
text->clear();
newCursor = 0;
redrawPos = newCursor;
break;
case '\n': // return, tab
case '\r':
case '\t':
activate(gFalse);
if (tabTarget)
if ((widget = parent->findWidget(tabTarget)))
widget->activate(gTrue);
newCursor = newSelectionEnd = cursor;
break;
default: // insert char
if (s[0] >= 0x20) {
if (selectionEnd > cursor)
text->del(cursor, selectionEnd - cursor);
text->insert(cursor, s);
redrawPos = cursor;
++newCursor;
}
break;
}
} else { // ignore weird X keysyms
killSelection = gFalse;
}
newSelectionEnd = killSelection ? newCursor : selectionEnd;
if (newCursor != cursor || newSelectionEnd != selectionEnd ||
redrawPos >= 0) {
xorCursor();
cursor = newCursor;
selectionEnd = newSelectionEnd;
redrawTail(redrawPos);
if (active)
xorCursor();
}
}
void LTKTextIn::clearSelection() {
if (active)
xorCursor();
selectionEnd = cursor;
if (active)
xorCursor();
}
void LTKTextIn::paste(GString *str) {
int redrawPos;
if (active)
xorCursor();
text->insert(cursor, str);
redrawPos = cursor;
cursor += str->getLength();
selectionEnd = cursor;
redrawTail(redrawPos);
if (active)
xorCursor();
}
int LTKTextIn::xToCursor(int mx) {
XCharStruct extents;
int direction, ascent, descent;
int x1, x2;
int pos;
if (mx < horizBorder)
return firstChar > 0 ? firstChar - 1 : 0;
x2 = horizBorder;
for (pos = firstChar; pos < text->getLength(); ++pos) {
XTextExtents(fontStruct, text->getCString() + pos, 1,
&direction, &ascent, &descent, &extents);
x1 = x2;
x2 += extents.width;
if (mx < (x1 + x2) / 2)
break;
}
return pos;
}
int LTKTextIn::cursorToX(int cur) {
XCharStruct extents;
int direction, ascent, descent;
int x;
x = horizBorder;
if (cur > firstChar) {
XTextExtents(fontStruct, text->getCString() + firstChar,
cur - firstChar,
&direction, &ascent, &descent, &extents);
x += extents.width;
}
return x;
}
void LTKTextIn::xorCursor() {
int tx1, tx2, ty;
int i, j;
ty = (height - textHeight) / 2;
// draw cursor
if (cursor == selectionEnd) {
tx1 = cursorToX(cursor);
XDrawLine(getDisplay(), xwin, getXorGC(),
tx1 - 1, ty, tx1 - 1, ty + textHeight - 1);
XDrawLine(getDisplay(), xwin, getXorGC(),
tx1, ty, tx1, ty + textHeight - 1);
// draw selection
} else {
i = (cursor >= firstChar) ? cursor : firstChar;
tx1 = cursorToX(